'''
Created on Nov 29, 2010

@author: dexen
'''

import os
import sys
import time
import shutil
import cPickle
import tempfile

from dexen.system.common import utils
from dexen.system.common.constants import NODES_ROOT_DIR


#===============================================================================
# ScoreMeta
#===============================================================================
MINIMIZE = -1
MAXIMIZE = 2

class ScoreMeta(object):
    def __init__(self, name, type, label=None):
        self.name = name
        self.type = type
        self.label = label
    
    def is_minimize(self):
        return self.type == MINIMIZE
    
    def is_maximize(self):
        return self.type == MAXIMIZE
    
    def get_header(self):
        out = "|  Score Name  | Score Type |\n"
        out += "-----------------------------"
        return out
    
    def __repr__(self):
        if self.is_minimize():
            type = "MINIMIZE"
        else: type = "MAXIMIZE" 
        out = "|%s|%s|"%(self.name.center(14), type.center(12))
        return out
#===============================================================================
# Job Meta Class
#===============================================================================
class JobMeta(object):
    def __init__(self, job_id, job_name, node_name, schema_zip, creation_time):
        """ Make sure schema_zip contains the files directly.
        """
        self.job_id = job_id
        self.job_name = job_name
        self.node_name = node_name
        self.schema_zip = schema_zip
        self.creation_time = time.time()
        self.root_dir = None
        self.old_dir = None
        self.old_sys_path = None

    def get_config_file(self):
        temp_dir = tempfile.mkdtemp(prefix="dexen_", suffix="_temp")
        utils.unzip(self.schema_zip, temp_dir)
        try:
            f = open(os.path.join(temp_dir, "client_config.py"), "r")
            content = f.read()
        except:
            content = None
        finally:
            f.close()
        utils.rmentry(temp_dir)
        return content
        
    def get_dir_name(self):
        return "Job%s_%s"%(self.job_id, self.job_name)
    
    def get_id(self):
        return self.job_id

    def get_name(self):
        return self.job_name

    def get_start_time(self):
        return self.creation_time
    
    def get_zip(self):
        return self.schema_zip

    def setup_schema(self):
        self.root_dir = tempfile.mkdtemp(prefix=self.job_name+"_", 
                                         dir=NODES_ROOT_DIR)
        self._unzip(self.root_dir)
    
    def teardown_schema(self):
        shutil.rmtree(self.root_dir)

    def setup_env(self):
        self.old_dir = os.getcwd()
        self.old_sys_path = sys.path
        sys.path = [self.root_dir] + sys.path
        os.chdir(self.root_dir)
    
    def reset_env(self):
        # WARNING: reset_env is supposed to be called after setup_env
        sys.path = self.old_sys_path
        os.chdir(self.old_dir)
        
    def get_master_task(self, master_env):
        # WARNING: Supposed to be called after setup_env
        module = __import__("master_task", fromlist=[""])
        cls = getattr(module, "MasterTask")
        obj = cls(master_env)
        return obj
    
    def _unzip(self, root_dir):
        utils.unzip(self.schema_zip, root_dir, mode='d')
    
        
#===============================================================================
# Task Meta Class
#===============================================================================
class TaskMeta(object):
    def __init__(self, class_obj, label, input_size, valid_func):
        self.class_name = class_obj.__name__
        self.module_name = class_obj.__module__
        self.label = label # needed for gui
        self.input_size = input_size 
        self.valid_func = cPickle.dumps(valid_func)
        self.name = class_obj.__module__ + "." + class_obj.__name__

    def get_valid_func(self):
        return cPickle.loads(self.valid_func)

    def get_input_size(self):
        return self.input_size

    def get_label(self):
        return self.label
   
    @classmethod
    def infer_name(cls, class_obj):
        return class_obj.__module__ + "." + class_obj.__name__
    
    def get_name(self):
        return self.name

    def _get_module(self):
        return __import__(self.module_name, fromlist=[""])
        
    def _get_cls(self):
        module = self._get_module()
        return getattr(module, self.class_name)
    
    def get_obj(self):
        return self._get_cls()()
    
    def __repr__(self):
        return "%s %s %s %s %d" %(self.name, self.module_name, self.class_name, 
                                  self.type, self.input_size)



